使用游戏特效系统
1. 引言
在游戏开发中,特效是提升游戏视觉体验的重要元素。它们可以增强游戏的氛围、突出关键事件,并提供即时的视觉反馈。本教程将介绍如何在 Dora SSR 引擎中使用 Effekseer 特效系统,以及如何使用引擎自带的 Particle 粒子系统。
2. 什么是 Effekseer?
Effekseer 是一个免费、开源的特效编辑器,支持 Windows、macOS 和 Linux 等多个平台。它允许美术人员和开发者创建各种粒子效果,如爆炸、火焰、光束等。Effekseer 支持多种渲染模式和高级特性,如:
- 粒子发射与控制:支持从点、线、面等多种形状发射粒子,并可对粒子的生命周期进行精细控制。
- 渲染特性:支持混合模式、纹理贴图、光照和阴影等。
- 多平台支持:可导出特效到多种游戏引擎和平台,包括 Dora SSR 等。
3. 使用 Effekseer
Dora SSR 引擎已经集成了 Effekseer 特效系统,开发者可以直接在游戏中加载和播放 Effekseer 编辑器生成的特效文件(通常以 .efk
或 .efkefc
为扩展名)。
3.1 EffekNode 类的使用
在 Dora SSR 中,可以使用 EffekNode
类来管理 Effekseer 特效的播放,并作为一个场景节点管理特效的几何位置、旋转和缩放等属性。以下是 EffekNode
类的主要方法和用法:
-
创建 EffekNode 对象
- Lua
- Teal
- TypeScript
- YueScript
local EffekNode <const> = require("EffekNode")
local effekNode = EffekNode()local EffekNode <const> = require("EffekNode")
local effekNode = EffekNode()import { EffekNode } from "Dora";
const effekNode = EffekNode();_ENV = Dora
effekNode = EffekNode! -
播放特效
- Lua
- Teal
- TypeScript
- YueScript
local handle = effekNode:play("Particle/effek/Laser01.efk", Vec2(100, 200), 0)
local handle = effekNode:play("Particle/effek/Laser01.efk", Vec2(100, 200), 0)
const handle = effekNode.play("Particle/effek/Laser01.efk", Vec2(100, 200), 0);
handle = effekNode\play "Particle/effek/Laser01.efk", Vec2(100, 200), 0
play
方法接收的参数如下:filename
:特效文件的路径。pos
(可选):播放特效的二维坐标,默认为(0, 0)
。z
(可选):播放特效的 Z 轴坐标,默认为0
。
-
停止特效
- Lua
- Teal
- TypeScript
- YueScript
effekNode:stop(handle)
effekNode:stop(handle)
effekNode.stop(handle);
effekNode\stop handle
handle
:play
方法返回的特效句柄。
-
监听特效结束事件
- Lua
- Teal
- TypeScript
- YueScript
effekNode:onEffekEnd(function(handle)
print("特效已结束,句柄:" .. handle)
end)effekNode:onEffekEnd(handle => {
print("特效已结束,句柄:" .. handle)
})effekNode.onEffekEnd(handle => {
print("特效已结束,句柄:" + handle);
});effekNode\onEffekEnd (handle) ->
print "特效已结束 ,句柄:#{handle}"
3.2 实战示例:播放一个激光特效
以下是一个完整的示例,展示如何在 Dora SSR 中播放一个名为 Laser01.efk
的激光特效,并在特效结束时进行回调处理。
- Lua
- Teal
- TypeScript
- YueScript
-- 引入必要的模块
local EffekNode <const> = require("EffekNode")
local Vec2 <const> = require("Vec2")
-- 创建 EffekNode 对象
local effekNode = EffekNode()
-- 设置特效节点整体的 3D 旋转角度
effekNode.angleY = -90
-- 在坐标 (100, 200) 处播放激光特效
local laserHandle = effekNode:play("Particle/effek/Laser01.efk", Vec2(100, 200))
-- 注册特效结束回调
effekNode:onEffekEnd(function(handle)
if handle == laserHandle then
print("激光特效已结束")
end
end)
-- 引入必要的模块
local EffekNode <const> = require("EffekNode")
local Vec2 <const> = require("Vec2")
-- 创建 EffekNode 对象
local effekNode = EffekNode()
-- 设置特效节点整体的 3D 旋转角度
effekNode.angleY = -90
-- 在坐标 (100, 200) 处播放激光特效
local laserHandle = effekNode:play("Particle/effek/Laser01.efk", Vec2(100, 200))
-- 注册特效结束回调
effekNode:onEffekEnd(function(handle: integer)
if handle == laserHandle then
print("激光特效已结束")
end
end)
// 引入必要的模块
import { EffekNode } from "Dora";
// 创建 EffekNode 对象
const effekNode = EffekNode();
// 设置特效节点整体的 3D 旋转角度
effekNode.angleY = -90;
// 在坐标 (100, 200) 处播放激光特效
const laserHandle = effekNode.play("Particle/effek/Laser01.efk", Vec2(100, 200));
// 注册特效结束回调
effekNode.onEffekEnd(handle => {
if (handle === laserHandle) {
print("激光特效已结束");
}
});
-- 引入必要的模块
_ENV = Dora
-- 创建 EffekNode 对象
effekNode = EffekNode!
-- 设置特效节点整体的 3D 旋转角度
effekNode.angleY = -90
-- 在坐标 (100, 200) 处播放激光特效
laserHandle = effekNode\play "Particle/effek/Laser01.efk", Vec2(100, 200)
-- 注册特效结束回调
effekNode\onEffekEnd (handle) ->
if handle == laserHandle
print "激光特效已结束"
3.3 控制特效的播放与停止
有时候,我们需要根据游戏逻辑来控制特效的播放和停止。例如,在玩家释放技能时播放特效,技能被打断时停止特效。
- Lua
- Teal
- TypeScript
- YueScript
-- 假设技能被打断,需要停止特效
effekNode:stop(laserHandle)
-- 假设技能被打断,需要停止特效
effekNode:stop(laserHandle)
// 假设技能被打断,需要停止特效
effekNode.stop(laserHandle);
-- 假设技能被打断,需要停止特效
effekNode\stop laserHandle
3.4 多个特效的管理
如果需要同时播放多个特效,可以分别保存每个特效的句柄,并在回调中进行区分。
- Lua
- Teal
- TypeScript
- YueScript
-- 播放多个特效
local handle1 = effekNode:play("Explosion.efk", Vec2(150, 250))
local handle2 = effekNode:play("Sparkle.efk", Vec2(200, 300))
-- 回调处理
effekNode:onEffekEnd(function(handle)
if handle == handle1 then
print("爆炸特效已结束")
elseif handle == handle2 then
print("闪光特效已结束")
end
end)
-- 播放多个特效
local handle1 = effekNode:play("Explosion.efk", Vec2(150, 250))
local handle2 = effekNode:play("Sparkle.efk", Vec2(200, 300)
-- 回调处理
effekNode:onEffekEnd(function(handle: integer)
if handle == handle1 then
print("爆炸特效已结束")
elseif handle == handle2 then
print("闪光特效已结束")
end
end)
// 播放多个特效
const handle1 = effekNode.play("Explosion.efk", Vec2(150, 250));
const handle2 = effekNode.play("Sparkle.efk", Vec2(200, 300));
// 回调处理
effekNode.onEffekEnd(handle => {
if (handle === handle1) {
print("爆炸特效已结束");
} else if (handle === handle2) {
print("闪光特效已结束");
}
});
-- 播放多个特效
handle1 = effekNode\play "Explosion.efk", Vec2 150, 250
handle2 = effekNode\play "Sparkle.efk", Vec2 200, 300
-- 回调处理
effekNode\onEffekEnd (handle) ->
if handle == handle1
print "爆炸特效已结束"
elseif handle == handle2
print "闪光特效已结束"
4. 使用 Particle 类
在 Effekseer 集成之前,Dora SSR 提供了 Particle
类来处理 2D 粒子特效。
然而,Particle
系统功能较为有限,主要依赖 CPU 进行计算,性能和效果都不如 Effekseer。因此,除非是只希望创建比较简单的粒子特效的场景,否则不推荐使用 Particle
类。
4.1 Particle 类的使用
-
创建 Particle 对象
- Lua
- Teal
- TypeScript
- YueScript
local Particle <const> = require("Particle")
local particle = Particle("effect.par")local Particle <const> = require("Particle")
local particle = Particle("effect.par")import { Particle } from "Dora";
const particle = Particle("effect.par");